/*
# pymoz, Python extension for the Mozilla Toolkit
# Copyright (C) 2012 Malek Hadj-Ali
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 3
# as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/


#include "pyException.h"

#include "prprf.h"

#include "nsIProgrammingLanguage.h"


static const nsCString gPythonName("Python");

static const char message_fmt[] = ": %s";
static const char filename_fmt[] = "  File \"%s\"";
static const char linenumber_fmt[] = ", line %d";
static const char sourceline_fmt[] = "\n    %s";


/*******************************************************************************
 utils
*******************************************************************************/

static void
nsCString_AppendFmt(nsCString& self, const char *fmt, ...)
{
    va_list ap;

    va_start(ap, fmt);
    char *buf = PR_vsmprintf(fmt, ap);
    va_end(ap);
    if (buf) {
        self.Append(buf);
        PR_smprintf_free(buf);
    }
    else {
        NS_RUNTIMEABORT("Allocation or other failure in PR_vsmprintf");
    }
}


static const char *
PyUnicode_AsPath(PyObject *unicode, PyObject **bytes)
{
    const char *result = NULL;

    PyObject *tmp = PyUnicode_EncodeFSDefault(unicode);
    if (tmp) {
        result = PyBytes_AS_STRING(tmp);
        *bytes = tmp;
    }
    return result;
}


static PyObject *
Py_GetSourceLine(PyObject *path, PyObject *lineno, PyObject *globals)
{
    PyObject *result = NULL;
    PyObject *linecache = NULL, *checkcache = NULL, *getline = NULL;
    PyObject *tmp = NULL;
    _Py_IDENTIFIER(checkcache);
    _Py_IDENTIFIER(getline);

    linecache = PyImport_ImportModuleNoBlock("linecache");
    if (!linecache) {
        goto done;
    }
    checkcache = _PyObject_GetAttrId(linecache, &PyId_checkcache);
    getline = _PyObject_GetAttrId(linecache, &PyId_getline);
    if (!checkcache || !getline) {
        goto done;
    }
    tmp = PyObject_CallFunctionObjArgs(checkcache, path, NULL);
    if (!tmp) {
        goto done;
    }
    result = PyObject_CallFunctionObjArgs(getline, path, lineno, globals, NULL);

done:
    Py_XDECREF(tmp);
    Py_XDECREF(getline);
    Py_XDECREF(checkcache);
    Py_XDECREF(linecache);
    return result;
}


// taken from Python/traceback.c
#define PyTraceBack_LIMIT 1000

static long
PyFrame_GetLimit()
{
    long limit = PyTraceBack_LIMIT;
    PyObject *pylimit = PySys_GetObject("tracebacklimit"); // borrowed

    if (pylimit) {
        PyObject *exc_type, *exc_value, *exc_tb;
        PyErr_Fetch(&exc_type, &exc_value, &exc_tb);
        limit = PyLong_AsLong(pylimit);
        if (limit == -1 && PyErr_Occurred()) {
            if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
                limit = PyTraceBack_LIMIT;
            }
            else {
                Py_XDECREF(exc_type);
                Py_XDECREF(exc_value);
                Py_XDECREF(exc_tb);
                return -1;
            }
        }
        else if (limit <= 0) {
            limit = 0;
        }
        PyErr_Restore(exc_type, exc_value, exc_tb);
    }
    return limit;
}


static PyObject *
PyFrame_GetSourceLine(PyFrameObject *frame, int lineno)
{
    PyObject *tmp = PyLong_FromLong(lineno);
    if (!tmp) {
        return NULL;
    }
    PyObject *result = Py_GetSourceLine(frame->f_code->co_filename, tmp,
                                        frame->f_globals);
    Py_DECREF(tmp);
    return result;
}


void
PyTraceback_FromLocation(const char *filename, const char *name, int lineno)
{
    PyObject *globals = Py_GetGlobals(); // borrowed
    if (!globals) {
        return;
    }
    PyCodeObject *code = PyCode_NewEmpty(filename, name, lineno);
    if (!code) {
        return;
    }
    PyFrameObject *frame = PyFrame_New(PyThreadState_GET(), code, globals,
                                       NULL);
    Py_DECREF(code);
    if (!frame) {
        return;
    }
    PyTraceBack_Here(frame);
    Py_DECREF(frame);
}


/*******************************************************************************
* pyStackFrame
*******************************************************************************/

NS_IMPL_ISUPPORTS1(pyStackFrame, nsIStackFrame)


/* nsIStackFrame */

NS_IMETHODIMP
pyStackFrame::GetLanguage(PRUint32 *aLanguage)
{
    *aLanguage = nsIProgrammingLanguage::PYTHON;
    return NS_OK;
}


NS_IMETHODIMP
pyStackFrame::GetLanguageName(char * *aLanguageName)
{
    *aLanguageName = ToNewCString(gPythonName);
    return NS_OK;
}


NS_IMETHODIMP
pyStackFrame::GetFilename(char * *aFilename)
{
    *aFilename = ToNewCString(mFilename);
    return NS_OK;
}


NS_IMETHODIMP
pyStackFrame::GetName(char * *aName)
{
    *aName = ToNewCString(mName);
    return NS_OK;
}


NS_IMETHODIMP
pyStackFrame::GetLineNumber(PRInt32 *aLineNumber)
{
    *aLineNumber = mLineNumber;
    return NS_OK;
}


NS_IMETHODIMP
pyStackFrame::GetSourceLine(char * *aSourceLine)
{
    *aSourceLine = ToNewCString(mSourceLine);
    return NS_OK;
}


NS_IMETHODIMP
pyStackFrame::GetCaller(nsIStackFrame * *aCaller)
{
    *aCaller = mCaller;
    NS_IF_ADDREF(*aCaller);
    return NS_OK;
}


NS_IMETHODIMP
pyStackFrame::ToString(char * *_retval NS_OUTPARAM)
{
    static const char caller_fmt[] = "%s\n";
    static const char name_fmt[] = ", in %s";
    nsCString result;

    if (mCaller) {
        char *caller = NULL;
        nsresult rv = mCaller->ToString(&caller);
        NS_ENSURE_SUCCESS(rv, rv);
        nsCString_AppendFmt(result, caller_fmt, caller);
        NS_Free(caller);
    }
    nsCString_AppendFmt(result, filename_fmt, mFilename.get());
    if (mLineNumber > 0) {
        nsCString_AppendFmt(result, linenumber_fmt, mLineNumber);
    }
    if (!mName.IsEmpty()) {
        nsCString_AppendFmt(result, name_fmt, mName.get());
    }
    if (!mSourceLine.IsEmpty()) {
        nsCString_AppendFmt(result, sourceline_fmt, mSourceLine.get());
    }
    *_retval = ToNewCString(result);
    return NS_OK;
}


/* pyStackFrame */

already_AddRefed<nsIStackFrame>
pyStackFrame::Create(PyFrameObject *aFrame, long limit)
{
    pyStackFrame *pySF = new pyStackFrame();
    if (!pySF) {
        PyErr_NoMemory();
        return NULL;
    }
    if (!pySF->Init(aFrame, limit)) {
        delete pySF;
        return NULL;
    }
    nsCOMPtr<nsIStackFrame> nsSF(do_QueryInterface(pySF));
    if (!nsSF) {
        PyErr_SetString(PyExc_TypeError, "QueryInterface failed");
        delete pySF;
        return NULL;
    }
    return nsSF.forget();
}


bool
pyStackFrame::Init(PyFrameObject *aFrame, long limit)
{
    // linenumber
    mLineNumber = PyFrame_GetLineNumber(aFrame);
    if (aFrame->f_code) {
        //filename
        if (aFrame->f_code->co_filename) {
            PyObject *pytmp = NULL;
            const char *aFilename =
                PyUnicode_AsPath(aFrame->f_code->co_filename, &pytmp);
            if (!aFilename) {
                Py_XDECREF(pytmp);
                return false;
            }
            mFilename.Assign(aFilename);
            Py_DECREF(pytmp);
            //sourceline
            if (!mFilename.IsEmpty() && mLineNumber) {
                PyObject *pysourceline =
                    PyFrame_GetSourceLine(aFrame, mLineNumber);
                if (!pysourceline) {
                    return false;
                }
                const char *aSourceLine = PyUnicode_AsUTF8(pysourceline);
                if (!aSourceLine) {
                    Py_DECREF(pysourceline);
                    return false;
                }
                mSourceLine.Assign(aSourceLine);
                Py_DECREF(pysourceline);
                mSourceLine.Trim(" \t\r\n", true, true);
            }
        }
        //name
        if (aFrame->f_code->co_name) {
            const char *aName = PyUnicode_AsUTF8(aFrame->f_code->co_name);
            if (!aName) {
                return false;
            }
            mName.Assign(aName);
        }
    }
    // caller
    if (aFrame->f_back && limit) {
        mCaller = Create(aFrame->f_back, --limit);
        if (!mCaller) {
            return false;
        }
    }
    return true;
}


pyStackFrame::pyStackFrame()
    : mFilename(),
      mName(),
      mLineNumber(0),
      mSourceLine()
{
}


pyStackFrame::~pyStackFrame()
{
}


/*******************************************************************************
* pyException
*******************************************************************************/

NS_IMPL_ISUPPORTS1(pyException, nsIException)


/* nsIException */

NS_IMETHODIMP
pyException::GetMessageMoz(char * *aMessage)
{
    *aMessage = ToNewCString(mMessage);
    return NS_OK;
}


NS_IMETHODIMP
pyException::GetResult(nsresult *aResult)
{
    *aResult = mResult;
    return NS_OK;
}


NS_IMETHODIMP
pyException::GetName(char * *aName)
{
    *aName = ToNewCString(mName);
    return NS_OK;
}


NS_IMETHODIMP
pyException::GetFilename(char * *aFilename)
{
    if (!mFilename.IsEmpty()) {
        *aFilename = ToNewCString(mFilename);
    }
    else if (mLocation) {
        return mLocation->GetFilename(aFilename);
    }
    return NS_OK;
}


NS_IMETHODIMP
pyException::GetLineNumber(PRUint32 *aLineNumber)
{
    if (mLineNumber) {
        *aLineNumber = mLineNumber;
    }
    else if (mLocation) {
        PRInt32 tmpLineNumber;
        nsresult rv = mLocation->GetLineNumber(&tmpLineNumber);
        NS_ENSURE_SUCCESS(rv, rv);
        *aLineNumber = tmpLineNumber;
    }
    return NS_OK;
}


NS_IMETHODIMP
pyException::GetColumnNumber(PRUint32 *aColumnNumber)
{
    *aColumnNumber = mColumnNumber;
    return NS_OK;
}


NS_IMETHODIMP
pyException::GetLocation(nsIStackFrame * *aLocation)
{
    *aLocation = mLocation;
    NS_IF_ADDREF(*aLocation);
    return NS_OK;
}


NS_IMETHODIMP
pyException::GetInner(nsIException * *aInner)
{
    return NS_ERROR_NOT_IMPLEMENTED;
}


NS_IMETHODIMP
pyException::GetData(nsISupports * *aData)
{
    return NS_ERROR_NOT_IMPLEMENTED;
}


NS_IMETHODIMP
pyException::ToString(char * *_retval NS_OUTPARAM)
{
    static const char context_fmt[] =
        "%s\n\nDuring handling of the above exception, "
        "another exception occurred:\n";
    static const char location_fmt[] =
        "\nTraceback (most recent call last):\n%s";
    static const char cause_fmt[] =
        "\n\nThe above exception was directly caused "
        "by the following exception:\n%s";
    nsCString result;

    if (mContext) {
        char *context = NULL;
        nsresult rv = mContext->ToString(&context);
        NS_ENSURE_SUCCESS(rv, rv);
        nsCString_AppendFmt(result, context_fmt, context);
        NS_Free(context);
    }
    result.Append(mName);
    if (!mMessage.IsEmpty()) {
        nsCString_AppendFmt(result, message_fmt, mMessage.get());
    }
    if (mLocation) {
        char *location = NULL;
        nsresult rv = mLocation->ToString(&location);
        NS_ENSURE_SUCCESS(rv, rv);
        nsCString_AppendFmt(result, location_fmt, location);
        NS_Free(location);
    }
    if (!mFilename.IsEmpty()) {
        result.Append("\n");
        nsCString_AppendFmt(result, filename_fmt, mFilename.get());
        if (mLineNumber > 0) {
            nsCString_AppendFmt(result, linenumber_fmt, mLineNumber);
        }
        if (!mSourceLine.IsEmpty()) {
            nsCString_AppendFmt(result, sourceline_fmt, mSourceLine.get());
            if (mColumnNumber > 0) {
                result.Append("\n    ");
                PRUint32 offset = mColumnNumber;
                while (--offset) {
                    result.Append(" ");
                }
                result.Append("^");
            }
        }
    }
    if (mCause) {
        char *cause = NULL;
        nsresult rv = mCause->ToString(&cause);
        NS_ENSURE_SUCCESS(rv, rv);
        nsCString_AppendFmt(result, cause_fmt, cause);
        NS_Free(cause);
    }
    *_retval = ToNewCString(result);
    return NS_OK;
}


/* pyException */

already_AddRefed<nsIException>
pyException::Create(PyObject *aExcValue, nsresult aResult)
{
    pyException *pyExc = new pyException();
    if (!pyExc) {
        PyErr_NoMemory();
        return NULL;
    }
    if (!pyExc->Init(aExcValue, aResult)) {
        delete pyExc;
        return NULL;
    }
    nsCOMPtr<nsIException> nsExc(do_QueryInterface(pyExc));
    if (!nsExc) {
        PyErr_SetString(PyExc_TypeError, "QueryInterface failed");
        delete pyExc;
        return NULL;
    }
    return nsExc.forget();
}


bool
pyException::Init(PyObject *aExcValue, nsresult aResult)
{
    PyObject *pymessage = NULL;
    _Py_IDENTIFIER(print_file_and_line);
    _Py_IDENTIFIER(__module__);
    _Py_IDENTIFIER(filename);
    _Py_IDENTIFIER(lineno);
    _Py_IDENTIFIER(offset);
    _Py_IDENTIFIER(text);
    _Py_IDENTIFIER(msg);

    if (_PyObject_HasAttrId(aExcValue, &PyId_print_file_and_line)) {
        // filename
        PyObject *pytmp = _PyObject_GetAttrId(aExcValue, &PyId_filename);
        if (!pytmp) {
            return false;
        }
        if (pytmp != Py_None) {
            const char *aFilename = PyUnicode_AsUTF8(pytmp);
            if (!aFilename) {
                Py_DECREF(pytmp);
                return false;
            }
            mFilename.Assign(aFilename);
        }
        Py_CLEAR(pytmp);
        // linenumber
        pytmp = _PyObject_GetAttrId(aExcValue, &PyId_lineno);
        if (!pytmp) {
            return false;
        }
        long aLineNumber = PyLong_AsLong(pytmp);
        Py_CLEAR(pytmp);
        if (aLineNumber < 0 && PyErr_Occurred()) {
            return false;
        }
        mLineNumber = aLineNumber;
        // columnnumber
        pytmp = _PyObject_GetAttrId(aExcValue, &PyId_offset);
        if (!pytmp) {
            return false;
        }
        if (pytmp != Py_None) {
            long aColumnNumber = PyLong_AsLong(pytmp);
            Py_CLEAR(pytmp);
            if (aColumnNumber < 0 && PyErr_Occurred()) {
                return false;
            }
            mColumnNumber = aColumnNumber;
        }
        else {
            Py_CLEAR(pytmp);
        }
        // sourceline
        pytmp = _PyObject_GetAttrId(aExcValue, &PyId_text);
        if (!pytmp) {
            return false;
        }
        if (pytmp != Py_None) {
            const char *aSourceLine = PyUnicode_AsUTF8(pytmp);
            if (!aSourceLine) {
                Py_DECREF(pytmp);
                return false;
            }
            mSourceLine.Assign(aSourceLine);
            mSourceLine.Trim(" \t\r\n", true, true);
        }
        Py_CLEAR(pytmp);
        // message
        pymessage = _PyObject_GetAttrId(aExcValue, &PyId_msg);
    }
    else {
        pymessage = PyObject_Str(aExcValue);
    }
    if (!pymessage) {
        return false;
    }
    const char *aMessage = PyUnicode_AsUTF8(pymessage);
    if (!aMessage) {
        Py_DECREF(pymessage);
        return false;
    }
    mMessage.Assign(aMessage);
    Py_DECREF(pymessage);
    // result
    mResult = aResult;
    // name
    PyTypeObject *aExcType = Py_TYPE(aExcValue);
    PyObject *pyname = _PyObject_GetAttrId((PyObject *)aExcType,
                                           &PyId___module__);
    if (pyname) {
        const char *aName = PyUnicode_AsUTF8(pyname);
        if (!aName) {
            Py_DECREF(pyname);
            return false;
        }
        mName.Assign(aName);
        Py_DECREF(pyname);
    }
    const char *tp_name = aExcType->tp_name;
    if (mName == "builtins" || mName == "__main__") {
        mName.Assign(tp_name);
    }
    else {
        nsCString_AppendFmt(mName, ".%s", tp_name);
    }
    // location
    long limit = PyFrame_GetLimit();
    if (limit < 0) {
        return false;
    }
    if (limit) {
        PyObject *aTraceback = PyException_GetTraceback(aExcValue);
        if (aTraceback && PyTraceBack_Check(aTraceback)) {
            PyTracebackObject *tmp = (PyTracebackObject *)aTraceback;
            while (tmp->tb_next) {
                tmp = tmp->tb_next;
            }
            mLocation =
                pyStackFrame::Create((PyFrameObject *)tmp->tb_frame, limit);
            Py_DECREF(aTraceback);
            if (!mLocation) {
                return false;
            }
        }
        else {
            Py_XDECREF(aTraceback);
        }
    }
    // context
    PyObject *aContext = PyException_GetContext(aExcValue);
    if (aContext) {
        mContext = Create(aContext);
        Py_DECREF(aContext);
        if (!mContext) {
            return false;
        }
    }
    // cause
    PyObject *aCause = PyException_GetCause(aExcValue);
    if (aCause) {
        mCause = Create(aCause);
        Py_DECREF(aCause);
        if (!mCause) {
            return false;
        }
    }
    return true;
}


pyException::pyException()
    : mMessage(),
      mResult(0),
      mName(),
      mFilename(),
      mLineNumber(0),
      mColumnNumber(0),
      mSourceLine()
{
}


pyException::~pyException()
{
}


/*******************************************************************************
* pyWarning
*******************************************************************************/

NS_IMPL_ISUPPORTS2(pyWarning, nsIConsoleMessage, nsIScriptError)


/* nsIConsoleMessage */

NS_IMETHODIMP
pyWarning::GetMessageMoz(PRUnichar * *aMessage)
{
    return NS_ERROR_NOT_IMPLEMENTED;
}


/* nsIScriptError */

NS_IMETHODIMP
pyWarning::GetErrorMessage(nsAString & aErrorMessage)
{
    CopyUTF8toUTF16(mErrorMessage, aErrorMessage);
    return NS_OK;
}


NS_IMETHODIMP
pyWarning::GetSourceName(nsAString & aSourceName)
{
    CopyUTF8toUTF16(mSourceName, aSourceName);
    return NS_OK;
}


NS_IMETHODIMP
pyWarning::GetSourceLine(nsAString & aSourceLine)
{
    CopyUTF8toUTF16(mSourceLine, aSourceLine);
    return NS_OK;
}

NS_IMETHODIMP
pyWarning::GetLineNumber(PRUint32 *aLineNumber)
{
    *aLineNumber = mLineNumber;
    return NS_OK;
}


NS_IMETHODIMP
pyWarning::GetColumnNumber(PRUint32 *aColumnNumber)
{
    return NS_ERROR_NOT_IMPLEMENTED;
}


NS_IMETHODIMP
pyWarning::GetFlags(PRUint32 *aFlags)
{
    *aFlags = nsIScriptError::warningFlag;
    return NS_OK;
}


NS_IMETHODIMP
pyWarning::GetCategory(char * *aCategory)
{
    *aCategory = ToNewCString(gPythonName);
    return NS_OK;
}


NS_IMETHODIMP
pyWarning::GetTimeStamp(PRInt64 *aTimeStamp)
{
    return NS_ERROR_NOT_IMPLEMENTED;
}


NS_IMETHODIMP
pyWarning::GetOuterWindowID(PRUint64 *aOuterWindowID)
{
    return NS_ERROR_NOT_IMPLEMENTED;
}


NS_IMETHODIMP
pyWarning::GetInnerWindowID(PRUint64 *aInnerWindowID)
{
    return NS_ERROR_NOT_IMPLEMENTED;
}


NS_IMETHODIMP
pyWarning::Init(const PRUnichar * message, const PRUnichar * sourceName,
                const PRUnichar * sourceLine, PRUint32 lineNumber,
                PRUint32 columnNumber, PRUint32 flags, const char * category)
{
    return NS_ERROR_NOT_IMPLEMENTED;
}


NS_IMETHODIMP
pyWarning::InitWithWindowID(const PRUnichar * message,
                            const PRUnichar * sourceName,
                            const PRUnichar * sourceLine, PRUint32 lineNumber,
                            PRUint32 columnNumber, PRUint32 flags,
                            const char * category, PRUint64 innerWindowID)
{
    return NS_ERROR_NOT_IMPLEMENTED;
}


NS_IMETHODIMP
pyWarning::ToString(nsACString & _retval NS_OUTPARAM)
{
    nsCString result;

    result.Assign(mErrorMessage);
    if (!mSourceName.IsEmpty()) {
        result.Append("\n");
        nsCString_AppendFmt(result, filename_fmt, mSourceName.get());
        if (mLineNumber > 0) {
            nsCString_AppendFmt(result, linenumber_fmt, mLineNumber);
        }
        if (!mSourceLine.IsEmpty()) {
            nsCString_AppendFmt(result, sourceline_fmt, mSourceLine.get());
        }
    }
    _retval.Assign(result);
    return NS_OK;
}


/* pyWarning */

already_AddRefed<nsIScriptError>
pyWarning::Create(PyObject *aMessage, PyObject *aCategory,
                  PyObject *aFilename, PyObject *aLineno, PyObject *aLine)
{
    pyWarning *pyWarn = new pyWarning();
    if (!pyWarn) {
        PyErr_NoMemory();
        return NULL;
    }
    if (!pyWarn->Init(aMessage, aCategory, aFilename, aLineno, aLine)) {
        delete pyWarn;
        return NULL;
    }
    nsCOMPtr<nsIScriptError> nsWarn(do_QueryInterface(pyWarn));
    if (!nsWarn) {
        PyErr_SetString(PyExc_TypeError, "QueryInterface failed");
        delete pyWarn;
        return NULL;
    }
    return nsWarn.forget();
}


bool
pyWarning::Init(PyObject *aMessage, PyObject *aCategory,
                PyObject *aFilename, PyObject *aLineno, PyObject *aLine)
{
    // errormessage
    mErrorMessage.Assign(((PyTypeObject *)aCategory)->tp_name);
    PyObject *pytmp = PyObject_Str(aMessage);
    if (!pytmp) {
        return false;
    }
    const char *aErrorMessage = PyUnicode_AsUTF8(pytmp);
    if (!aErrorMessage) {
        Py_DECREF(pytmp);
        return false;
    }
    nsCString_AppendFmt(mErrorMessage, message_fmt, aErrorMessage);
    Py_CLEAR(pytmp);
    // sourcename
    const char *aSourceName = PyUnicode_AsUTF8(aFilename);
    if (!aSourceName) {
        return false;
    }
    mSourceName.Assign(aSourceName);
    // linenumber
    long aLineNumber = PyLong_AsLong(aLineno);
    if (aLineNumber < 0 && PyErr_Occurred()) {
        return false;
    }
    mLineNumber = aLineNumber;
    // sourceline
    if (aLine != Py_None) {
        Py_INCREF(aLine);
        pytmp = aLine;
    }
    else {
        PyObject *globals = Py_GetGlobals(); // borrowed
        if (!globals) {
            return false;
        }
        pytmp = Py_GetSourceLine(aFilename, aLineno, globals);
        if (!pytmp) {
            return false;
        }
    }
    const char *aSourceLine = PyUnicode_AsUTF8(pytmp);
    if (!aSourceLine) {
        Py_DECREF(pytmp);
        return false;
    }
    mSourceLine.Assign(aSourceLine);
    Py_CLEAR(pytmp);
    mSourceLine.Trim(" \t\r\n", true, true);
    return true;
}


pyWarning::pyWarning()
    : mErrorMessage(),
      mSourceName(),
      mSourceLine(),
      mLineNumber(0)
{
}


pyWarning::~pyWarning()
{
}
